#include "Path.h"

#include "Logging.h"
#include "LeString.h"

#include <stdio.h>  /* defines FILENAME_MAX */
#ifdef _WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#include <dirent.h>
#define GetCurrentDir getcwd
#endif

#include <boost/filesystem.hpp>

le::Path::Path()
{

}

le::Path::Path( const std::string& path )
{
	// This is to make sure all paths are normalized. Required for path algorithms
	m_StoredPath = path;
	m_StoredPath = le::String::Replace(m_StoredPath, "\\\\", "/");
	m_StoredPath = le::String::Replace(m_StoredPath, "\\", "/");
}

le::Path::Path( const char* path )
{
	m_StoredPath = std::string(path);
	m_StoredPath = le::String::Replace(m_StoredPath, "\\\\", "/");
	m_StoredPath = le::String::Replace(m_StoredPath, "\\", "/");
}

le::Path::~Path()
{

}

le::Path le::Path::NormalizePath( const le::Path& path )
{
	std::string outPath(path.m_StoredPath);
	outPath = le::String::Replace(outPath, "\\\\", "/");
	outPath = le::String::Replace(outPath, "\\", "/");

	return le::Path(outPath);
}

std::string le::Path::GetExtension( const le::Path& path )
{
	std::string outExtenstion(path.m_StoredPath);
	size_t indexOfDot = outExtenstion.rfind('.');
	if (indexOfDot != std::string::npos)
	{
		return outExtenstion.substr(indexOfDot, outExtenstion.length() - indexOfDot);
	}

	return "";
}

std::string le::Path::GetFileName( const le::Path& path )
{
	std::string outFileName(path.m_StoredPath);
	size_t indexOfSlash = outFileName.rfind('/');

	if (indexOfSlash != std::string::npos)
	{
		indexOfSlash += 1;
		return outFileName.substr(indexOfSlash, outFileName.length() - indexOfSlash);
	}

	return "";
}

std::string le::Path::GetFileNameNoExtension( const le::Path& path )
{
	std::string outFileName(path.m_StoredPath);
	size_t indexOfSlash = outFileName.rfind('/');

	if (indexOfSlash != std::string::npos)
	{
		indexOfSlash += 1;
		outFileName = outFileName.substr(indexOfSlash, outFileName.length() - indexOfSlash);
		size_t indexOfDot = outFileName.rfind('.');
		if (indexOfDot != std::string::npos)
		{
			return outFileName.substr(0, indexOfDot);
		}
	}

	return "";
}

std::string le::Path::GetResidingFolder( const le::Path& path )
{
	TODO("Please implement me");
	return "";
}

std::string le::Path::GetFolderPath( const le::Path& path )
{
	std::string outFileName(path.m_StoredPath);
	size_t indexOfSlash = outFileName.rfind('/');

	if (indexOfSlash != std::string::npos)
	{
		return outFileName.substr(0, indexOfSlash);
	}
	return "";
}

std::string le::Path::GetWorkDirectory()
{
	char rootPath[1024];
	std::string currentWorkingDirectory(GetCurrentDir(rootPath, 1024 * sizeof(char)));
	return currentWorkingDirectory;
}

std::string le::Path::GetAbsolutePath( const le::Path& relativePath )
{
	// TODO: This is not supported at the moment
	// TODO: this is wrong at the moment as you can see. This should get or read from a installed variable or from a fixed path relative to the build dir
	std::string outString = GetWorkDirectory();
	outString.append("/../../../../../");
	outString.append(relativePath.ToChar());
	return outString;
}

size_t le::Path::GetFilesInPath( const le::Path& path, const char* filter, bool recursive, std::vector<le::Path>& out )
{
	try
	{
		if (boost::filesystem::exists(path.ToChar()))    // does p actually exist?
		{
			if (boost::filesystem::is_directory(path.ToChar()))      // is p a directory?
			{
				boost::filesystem::directory_iterator end;
				for (boost::filesystem::directory_iterator iter(path.ToChar()); iter !=  end; ++iter)
				{
					if (boost::filesystem::is_directory(iter->status()) && recursive)
					{

						// GetFilesInPath(le::Path(iter->path().c_str()), filter, recursive, out);
					}
					
					else if ( boost::filesystem::is_regular_file(iter->status())) // see below
					{
						LOG(le::eLog_Info, "echo %ls\n", (wchar_t*)iter->path().c_str());
					}

				}
			}
		}
	}

	catch (const boost::filesystem::filesystem_error& /*ex*/)
	{
		// TODO: add a warning here.
	}
	return out.size();
}
